﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenControls.Core;
using System.Drawing;
using BoneSoft.CSS;
using System.Windows.Forms;
using OpenControls.Controls;

namespace OpenControls
{
    public class FormBaseCustomizer : ControlCustomizer<FormCustomizable, Form>
    {

        #region Private Fields

        private string[] formBorders = new string[] 
        { 
            "Sizeable", "FixedSingle", "Fixed3D",
            "FixedDialog", "FixedToolWindow", "SizeableToolWindow", 
            "None"
        };

        #endregion

        #region Private Methods

        private FormBorderStyle GetFormBorder(string item)
        {
            switch (item.ToLower())
            {
                case "fixedsingle":
                    return FormBorderStyle.FixedSingle;
                case "fixed3d":
                    return FormBorderStyle.Fixed3D;
                case "FixedDialog":
                    return FormBorderStyle.FixedDialog;
                case "FixedToolWindow":
                    return FormBorderStyle.FixedToolWindow;
                case "sizeable":
                    return FormBorderStyle.Sizable;
                case "sizeabletoolwindow":
                    return FormBorderStyle.SizableToolWindow;
                case "none":
                    return FormBorderStyle.None;
                default:
                    break;
            }

            return FormBorderStyle.None;
        }

        #endregion

        #region Override Methods

        public override IStyle GetCustomization()
        {
            throw new NotImplementedException();
        }

        public override void PerformCustomization(ICustomizableControl control)
        {
            this.ApplyColorCustomization(control);
            this.ApplyFontCustomization(control);
            this.ApplyBorderCustomization(control);
        }

        public override void PerformCustomization(ICustomizableControl control, IStyle style)
        {
            control.Style = style;
            this.PerformCustomization(control);
        }

        public override void ApplyColorCustomization(ICustomizableControl control)
        {
            Color? color;
            Declaration declaration;
            RuleSet rule;

            rule = this.Utils.FindRuleSet(control.Style, control.CssClass);

            if (rule != null)
            {
                declaration = rule["background-color"];

                if (declaration != null && declaration.Expression.Terms.Count == 1)
                {
                    color = this.Utils.GetColor(declaration.Expression.Terms[0].Value);
                    (control as Form).BackColor = (color == null) ? Color.Empty : color.Value;
                }
                else
                    throw new ArgumentException("The background-color declaration shall not have more than 1 term");

                declaration = rule["color"];
                if (declaration != null)
                {
                    color = this.Utils.GetColor(declaration.Expression.Terms[0].Value);
                    (control as Form).ForeColor = (color == null) ? Color.Black : color.Value;
                }
            }

            color = null;
            declaration = null;
            rule = null;
        }

        public override void ApplyFontCustomization(ICustomizableControl control)
        {
            float fontSize = 9.75f;
            Font font = null;
            FontFamily fontFamily = null;
            FontStyle fontStyle;
            Declaration declaration;
            bool useBold = false;
            bool useUnderline = false;
            bool useLinethrough = false;
            RuleSet rule = this.Utils.FindRuleSet(control.Style, control.CssClass);


            declaration = rule["font-family"];

            if (declaration != null)
            {
                if (declaration.Expression.Terms.Count > 1)
                    throw new ArgumentException("The font-family declaration shall have only 1 term.");

                fontFamily = new FontFamily(declaration.Expression.Terms[0].Value);
            }

            declaration = rule["font-size"];

            if (declaration != null)
            {
                if (!float.TryParse(declaration.Expression.Terms[0].Value, out fontSize))
                    throw new ArgumentException("The font-size declaration contains invalid values.");
            }

            declaration = rule["font-weight"];

            if (declaration != null)
            {
                if (declaration.Expression.Terms.Count > 1)
                    throw new ArgumentException("The font-weight declaration shall have only 1 term.");

                if ((new string[] { "bold", "bolder" }).Contains<string>(declaration.Expression.Terms[0].Value.ToLower()))
                    useBold = true;
            }

            declaration = rule["text-decoration"];

            if (declaration != null)
            {
                // the System.Windows.Forms.Control class only support the Underline and Strikeout styles

                if (declaration.Expression.Terms.Count == 1)
                {
                    useUnderline = (
                                   declaration.Expression.Terms[0].Value.ToLower() == "underline" ? true : false
                               );
                    useLinethrough = (
                                    declaration.Expression.Terms[0].Value.ToLower() == "line-through" ? true : false
                                );
                }
                else if (declaration.Expression.Terms.Count == 2)
                {
                    useUnderline = (
                                    declaration.Expression.Terms[0].Value.ToLower() == "underline" ? true : false
                                    ||
                                    declaration.Expression.Terms[1].Value.ToLower() == "underline" ? true : false
                                );

                    useLinethrough = (
                                        declaration.Expression.Terms[0].Value.ToLower() == "line-through" ? true : false
                                        ||
                                        declaration.Expression.Terms[1].Value.ToLower() == "line-through" ? true : false
                                    );
                }
                else
                    throw new ArgumentException("The text-decoration declaration shall have only 1 term.");
            }

            /*
             
             *  TODO: The font-variant and text-transform declarations needs to be best understood.
             
             */

            fontStyle = (useBold ? FontStyle.Bold : FontStyle.Regular) |
                        (useUnderline ? FontStyle.Underline : FontStyle.Regular) |
                        (useLinethrough ? FontStyle.Strikeout : FontStyle.Regular);

            font = new Font(fontFamily, fontSize, fontStyle);

            (control as Form).Font = font;
        }

        public override void ApplyBorderCustomization(ICustomizableControl control)
        {
            RuleSet rule;
            Declaration declaration;

            rule = this.Utils.FindRuleSet(control.Style, control.CssClass);

            if (rule != null)
            {
                declaration = rule["border"];

                if (declaration != null)
                {
                    foreach (string item in this.formBorders)
                    {
                        if (item.ToLower().Equals(declaration.Expression.Terms[0].Value.ToLower()))
                            (control as Form).FormBorderStyle = this.GetFormBorder(item);
                    }
                }

                declaration = rule["MaximizeBox"];
                if (declaration != null)
                    (control as Form).MaximizeBox = Convert.ToBoolean(declaration.Expression.Terms[0].Value);

                declaration = rule["MinimizeBox"];
                if (declaration != null)
                    (control as Form).MinimizeBox = Convert.ToBoolean(declaration.Expression.Terms[0].Value);

                declaration = rule["ControlBox"];
                if (declaration != null)
                    (control as Form).ControlBox = Convert.ToBoolean(declaration.Expression.Terms[0].Value);

                declaration = rule["ShowInTaskBar"];
                if (declaration != null)
                    (control as Form).ShowInTaskbar = Convert.ToBoolean(declaration.Expression.Terms[0].Value);

                declaration = rule["ShowIcon"];
                if (declaration != null)
                    (control as Form).ShowIcon = Convert.ToBoolean(declaration.Expression.Terms[0].Value);
            }
        }

        public override void ApplyParentCustomization(ICustomizableControl control)
        {

        }

        public override void CloneCustomization(ICustomizableControl control)
        {
            IStyle oldStyle = this.Control.Style;
            this.PerformCustomization(this.Control, control.Style);
        }

        #endregion

    }
}